package com.cupdata.zicon.jdk7concurrent.chapter3;

import java.util.concurrent.Semaphore;

/**
 * This method
shows the three steps you must follow when you use a semaphore to implement a critical
section, and protect the access to a shared resource:
1. First, you acquire the semaphore, with the acquire() method.
2. Then, you do the necessary operations with the shared resource.
3. Finally, release the semaphore with the release() method.
 * @author SunYabing
 *
 */
public class SemaphoreTest {
	public static void main(String[] args){
		PrintQueue printQueue = new PrintQueue();
		Thread[] thread = new Thread[10];
		for(int i = 0; i< 10; i++){
			thread[i] = new Thread(new Job(printQueue),"Thread"+i);
		}
		
		for(int i = 0; i< 10; i++){
			thread[i].start();
		}
	}
}

class PrintQueue {
	private final Semaphore semaphore;

	public PrintQueue() {
		semaphore = new Semaphore(1);//同一时刻,只允许一个线程访问
	}

	public void printJob(Object document) {
		try {
			semaphore.acquire();
			long duration = (long) (Math.random() * 10);
			System.out.printf(
					"%s: PrintQueue: Printing a Job during %d seconds\n",
					Thread.currentThread().getName(), duration);
			Thread.sleep(duration);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			semaphore.release();
		}
	}
}

class Job implements Runnable {
	private PrintQueue printQueue;

	public Job(PrintQueue printQueue) {
		this.printQueue = printQueue;
	}

	@Override
	public void run() {
		System.out.printf("%s: Going to print a job\n", Thread.currentThread()
				.getName());
		printQueue.printJob(new Object());
		System.out.printf("%s: The document has been printed\n", Thread
				.currentThread().getName());
	}
}
